using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Cors.Internal;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Castle.Facilities.Logging;
using Swashbuckle.AspNetCore.Swagger;
using Abp.AspNetCore;
using Abp.Castle.Logging.Log4Net;
using Abp.Extensions;
using Abp.AspNetCore.SignalR.Hubs;
using Microsoft.AspNetCore.Mvc;
using Hangfire;

using JYJ.AiYard.Configuration;
using JYJ.AiYard.Identity;
using JYJ.AiYard.IdentityServer;
using JYJ.AiYard.Authentication.JwtBearer;
using Swashbuckle.AspNetCore.SwaggerUI;
using Hangfire.RecurringJobExtensions;
using JYJ.AiYard.Common;
using Microsoft.Extensions.Options;
using Senparc.CO2NET;
using JYJ.AiYard.Service;
using JYJ.AiYard.Swagger;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Microsoft.AspNetCore.SpaServices.AngularCli;

namespace JYJ.AiYard.Web.Host.Startup
{
    public class Startup
    {
        private const string _defaultCorsPolicyName = "AiYard";

        private readonly IHostingEnvironment _hostingEnvironment;
        private readonly IConfigurationRoot _appConfiguration;

        public Startup(IHostingEnvironment env)
        {
            _hostingEnvironment = env;
            _appConfiguration = env.GetAppConfiguration();
        }

        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            // MVC
            services.AddMvc(
                options => options.Filters.Add(new CorsAuthorizationFilterFactory(_defaultCorsPolicyName))
            ).SetCompatibilityVersion(CompatibilityVersion.Version_2_2).AddJsonOptions(option =>
            {
                option.SerializerSettings.Converters = new List<JsonConverter>()
                {
                    new StringEnumConverter()
                };

            });
            // Add Wchat
            SenparcWXConfigurer.AddWechat(services, _appConfiguration);


            // Add SingalR
            services.AddSignalR(options => { options.EnableDetailedErrors = true; });

            // 配置前后端分离跨域
            services.AddCors(
                options => options.AddPolicy(
                    _defaultCorsPolicyName,
                    builder => builder
                        .WithOrigins(
                            // App:CorsOrigins in appsettings.json can contain more than one address separated by comma.
                            _appConfiguration["App:CorsOrigins"]
                                .Split(",", StringSplitOptions.RemoveEmptyEntries)
                                .Select(o => o.RemovePostFix("/"))
                                .ToArray()
                        )
                        .SetIsOriginAllowedToAllowWildcardSubdomains()
                        .AllowAnyHeader()
                        .AllowAnyMethod()
                        .AllowCredentials()
                )
            );




            IdentityRegistrar.Register(services);
            AuthConfigurer.Configure(services, _appConfiguration);


            // IdentityServer4 配置
            if (bool.Parse(_appConfiguration["IdentityServer:IsEnabled"]))
            {
                IdentityServerRegistrar.Register(services, _appConfiguration);
            }


            if (WebConsts.SwaggerUiEnabled)
            {
                //Swagger -启用此行以及Configure方法中的相关行，以启用Swagger UI
                services.AddSwaggerGen(options =>
                {
                    options.SwaggerDoc("v1",
                        new Info
                        {
                            Title = "52ABP-PRO API",
                            Version = "v1",
                            Description = "52ABP-PRO 的动态WEBAPI管理端，可以进行测试和调用API。",
                            TermsOfService = "https://gitee.com/ABPCN/52abp-pro",
                            Contact = new Contact
                            {
                                Name = "52abp.com",
                                Email = "ltm@ddxc.org",
                                Url = "https://www.52abp.com/"
                            },

                        });
                    // 使用字符串表示枚举
                    options.DescribeAllEnumsAsStrings();
                    // 使用 camel case 的枚举
                    //options.DescribeStringEnumsInCamelCase();
                    // 对应client枚举转为字符串对应值
                    options.SchemaFilter<SwaggerEnumSchemaFilter>();
                    // 支持非body内容中的枚举
                    options.ParameterFilter<SwaggerEnumParameterFilter>();
                    options.OrderActionsBy(x => x.RelativePath);
                    options.DescribeAllParametersInCamelCase();
                    options.UseReferencedDefinitionsForEnums();
                    options.OperationFilter<SwaggerOperationIdFilter>();

                    //使用相对路径获取应用程序所在目录
                    options.DocInclusionPredicate((docName, description) => true);

                    var basePath = Path.GetDirectoryName(typeof(Program).Assembly.Location);
                    var commentsFileName = typeof(AiYardApplicationModule).Assembly.GetName().Name +
                                           ".XML";
                    var xmlPath = Path.Combine(basePath, commentsFileName);
                    //添加注释
                    options.IncludeXmlComments(xmlPath);
                    // 表示需要授权，授权按钮处理逻辑在静态文件 wwwroot/swagger/ui/index.html 中
                    options.AddSecurityDefinition("Bearer", new BasicAuthScheme());
                });

            }

            if (WebConsts.HangfireDashboardEnabled)
            {
                // 启用hangfire
                services.AddHangfire(config =>
                {
                    config.UseSqlServerStorage(_appConfiguration.GetConnectionString("Default"));
                    //   config.UseRecurringJob(typeof(RecurringJobService)); //注入Hnagfire的测试服务
                });
            }




            // 配置abp和依赖注入
            return services.AddAbp<AiYardWebHostModule>(
                options =>
                {
                    // 配置log4net
                    options.IocManager.IocContainer.AddFacility<LoggingFacility>(f => f.UseAbpLog4Net().WithConfig("log4net.config"));
                }
            );
        }

        public void Configure(IApplicationBuilder app,
            IHostingEnvironment env,
            ILoggerFactory loggerFactory,
            IOptions<SenparcSetting> senparcSetting)
        {
            // 初始化ABP框架
            app.UseAbp(options =>
            {
                options.UseAbpRequestLocalization = false;
            });

            // Use Wechat
            SenparcWXConfigurer.UseWechat(env, senparcSetting.Value);

            // 启用CORS
            app.UseCors(_defaultCorsPolicyName);

            // 启用静态文件
            app.UseStaticFiles();

            // 启用校验
            app.UseAuthentication();
            app.UseJwtTokenMiddleware();

            // 如果使用Identity Server4
            if (bool.Parse(_appConfiguration["IdentityServer:IsEnabled"]))
            {
                app.UseJwtTokenMiddleware("IdentityBearer");
                app.UseIdentityServer();
            }

            app.UseAbpRequestLocalization();


            // 启用SignalR
            app.UseSignalR(routes =>
            {
                routes.MapHub<AbpCommonHub>("/signalr");
            });

          

            //是否启用Hangfire
            if (WebConsts.HangfireDashboardEnabled)
            {
                //配置服务最大重试次数值
                GlobalJobFilters.Filters.Add(new AutomaticRetryAttribute { Attempts = 5 });
                //设置Hangfire服务可选参数
                var jobOptions = new BackgroundJobServerOptions
                {
                    //wait all jobs performed when BackgroundJobServer shutdown.
                    ShutdownTimeout = TimeSpan.FromMinutes(30),
                    Queues = new[] { "default", "jobs" },//队列名称，只能为小写
                    WorkerCount = 3,//Environment.ProcessorCount * 5, //并发任务数 Math.Max(Environment.ProcessorCount, 20)
                    ServerName = "yoyocms.hangfire",//服务器名称
                };


                ////Hangfire dashboard &server(Enable to use Hangfire instead of default job manager)
                app.UseHangfireDashboard("/hangfire", new DashboardOptions
                {
                    // Authorization = new[] { new AbpHangfireAuthorizationFilter() }
                });
                app.UseHangfireServer(jobOptions);
                // app.UseHangfireServer();

            }



            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "defaultWithArea",
                    template: "{area}/{controller=Home}/{action=Index}/{id?}");

                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });

            if (WebConsts.SwaggerUiEnabled)
            {  
                // 使中间件能够作为JSON端点提供生成的Swagger
                app.UseSwagger();
                // 使中间件能够提供swagger-ui(HTML、JS、CSS等)
                app.UseSwaggerUI(options =>
                {
                    options.SwaggerEndpoint("/swagger/v1/swagger.json", "AiYard API V1");
                    options.DocExpansion(DocExpansion.None);
                    options.EnableDeepLinking();

                    options.IndexStream = () => Assembly.GetExecutingAssembly()
                        .GetManifestResourceStream("JYJ.AiYard.Web.Host.wwwroot.swagger.ui.index.html");
                }); // URL: /swagger

            }

             
        }
    }
}
